#include <asm/pal.h>
#include <asm/sal.h>
#include <asm/meminit.h>
+#include <asm/fpswa.h>
#include <xen/compile.h>
#include <xen/acpi.h>
} \
} while (0)
+// builds a hypercall bundle at domain physical address
+static void dom_fpswa_hypercall_patch(struct domain *d)
+{
+ unsigned long *entry_imva, *patch_imva;
+ unsigned long entry_paddr = FW_HYPERCALL_FPSWA_ENTRY_PADDR;
+ unsigned long patch_paddr = FW_HYPERCALL_FPSWA_PATCH_PADDR;
+
+#ifndef CONFIG_XEN_IA64_DOM0_VP
+ if (d == dom0) {
+ entry_paddr += dom0_start;
+ patch_paddr += dom0_start;
+ }
+#endif
+ ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, entry_paddr);
+ ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, patch_paddr);
+ entry_imva = (unsigned long *) domain_mpa_to_imva(d, entry_paddr);
+ patch_imva = (unsigned long *) domain_mpa_to_imva(d, patch_paddr);
+
+ *entry_imva++ = patch_paddr;
+ *entry_imva = 0;
+ build_hypercall_bundle(patch_imva, d->arch.breakimm, FW_HYPERCALL_FPSWA, 1);
+}
+
// builds a hypercall bundle at domain physical address
static void dom_efi_hypercall_patch(struct domain *d, unsigned long paddr, unsigned long hypercall)
{
build_hypercall_bundle(imva, d->arch.breakimm, hypercall, 1);
}
-
// builds a hypercall bundle at domain physical address
static void dom_fw_hypercall_patch(struct domain *d, unsigned long paddr, unsigned long hypercall,unsigned long ret)
{
struct ia64_sal_systab *sal_systab;
struct ia64_sal_desc_entry_point *sal_ed;
struct ia64_sal_desc_ap_wakeup *sal_wakeup;
+ fpswa_interface_t *fpswa_inf;
efi_memory_desc_t *efi_memmap, *md;
struct ia64_boot_param *bp;
unsigned long *pfn;
sal_systab = (void *) cp; cp += sizeof(*sal_systab);
sal_ed = (void *) cp; cp += sizeof(*sal_ed);
sal_wakeup = (void *) cp; cp += sizeof(*sal_wakeup);
+ fpswa_inf = (void *) cp; cp += sizeof(*fpswa_inf);
efi_memmap = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap);
bp = (void *) cp; cp += sizeof(*bp);
pfn = (void *) cp; cp += NFUNCPTRS * 2 * sizeof(pfn);
/* Initialise for EFI_SET_VIRTUAL_ADDRESS_MAP emulation */
d->arch.efi_runtime = efi_runtime;
+ d->arch.fpswa_inf = fpswa_inf;
if (args) {
if (arglen >= 1024)
sal_systab->checksum = -checksum;
+ /* Fill in the FPSWA interface: */
+ fpswa_inf->revision = fpswa_interface->revision;
+ dom_fpswa_hypercall_patch(d);
+ fpswa_inf->fpswa = (void *) FW_HYPERCALL_FPSWA_ENTRY_PADDR + start_mpaddr;
+
i = 0;
if (d == dom0) {
#ifndef CONFIG_XEN_IA64_DOM0_VP
bp->console_info.num_rows = 25;
bp->console_info.orig_x = 0;
bp->console_info.orig_y = 24;
- bp->fpswa = 0;
+ bp->fpswa = dom_pa((unsigned long) fpswa_inf);
if (d == dom0) {
// XXX CONFIG_XEN_IA64_DOM0_VP
// initrd_start address is hard coded in start_kernel()
#include <asm/pgalloc.h>
#include <asm/vcpu.h>
#include <asm/dom_fw.h>
+#include <asm/fpswa.h>
#include <public/sched.h>
extern unsigned long translate_domain_mpaddr(unsigned long);
unsigned long *vfn;
struct domain *d = current->domain;
efi_runtime_services_t *efi_runtime = d->arch.efi_runtime;
+ fpswa_interface_t *fpswa_inf = d->arch.fpswa_inf;
if (descriptor_version != EFI_MEMDESC_VERSION) {
printf ("efi_emulate_set_virtual_address_map: memory descriptor version unmatched\n");
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_variable,EFI_SET_VARIABLE);
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_next_high_mono_count,EFI_GET_NEXT_HIGH_MONO_COUNT);
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->reset_system,EFI_RESET_SYSTEM);
+
+ vfn = (unsigned long *) domain_mpa_to_imva(d, (unsigned long) fpswa_inf->fpswa);
+ *vfn++ = FW_HYPERCALL_FPSWA_PATCH_INDEX * 16UL + md->virt_addr;
+ *vfn = 0;
+ fpswa_inf->fpswa = (void *) (FW_HYPERCALL_FPSWA_ENTRY_INDEX * 16UL + md->virt_addr);
+ break;
}
/* The virtual address map has been applied. */
#include <linux/efi.h> /* FOR EFI_UNIMPLEMENTED */
#include <asm/sal.h> /* FOR struct ia64_sal_retval */
+#include <asm/fpswa.h> /* FOR struct fpswa_ret_t */
#include <asm/vcpu.h>
#include <asm/dom_fw.h>
return;
}
+static fpswa_ret_t
+fw_hypercall_fpswa (struct vcpu *v)
+{
+ return PSCBX(v, fpswa_ret);
+}
+
static IA64FAULT
fw_hypercall (struct pt_regs *regs)
{
struct vcpu *v = current;
struct sal_ret_values x;
efi_status_t efi_ret_value;
+ fpswa_ret_t fpswa_ret;
IA64FAULT fault;
unsigned long index = regs->r2 & FW_HYPERCALL_NUM_MASK_HIGH;
case FW_HYPERCALL_IPI:
fw_hypercall_ipi (regs);
break;
+ case FW_HYPERCALL_FPSWA:
+ fpswa_ret = fw_hypercall_fpswa (v);
+ regs->r8 = fpswa_ret.status;
+ regs->r9 = fpswa_ret.err0;
+ regs->r10 = fpswa_ret.err1;
+ regs->r11 = fpswa_ret.err2;
+ break;
default:
printf("unknown ia64 fw hypercall %lx\n", regs->r2);
regs->r8 = do_ni_hypercall();
#define FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_PADDR FW_HYPERCALL_PADDR(FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_INDEX)
#define FW_HYPERCALL_EFI_RESET_SYSTEM_PADDR FW_HYPERCALL_PADDR(FW_HYPERCALL_EFI_RESET_SYSTEM_INDEX)
+/*
+ * This is a hypercall number for IPI.
+ * A pseudo-entry-point is not presented to IPI hypercall. This hypercall number
+ * is used in xen_send_ipi of linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S.
+ */
+#define FW_HYPERCALL_IPI 0x400UL
+
+/*
+ * This is a hypercall number for FPSWA.
+ * FPSWA hypercall uses 2 bundles for a pseudo-entry-point and a hypercall-patch.
+ */
+#define FW_HYPERCALL_FPSWA_ENTRY_INDEX 0x83UL
+#define FW_HYPERCALL_FPSWA_PATCH_INDEX 0x84UL
+#define FW_HYPERCALL_FPSWA_ENTRY_PADDR FW_HYPERCALL_PADDR(FW_HYPERCALL_FPSWA_ENTRY_INDEX)
+#define FW_HYPERCALL_FPSWA_PATCH_PADDR FW_HYPERCALL_PADDR(FW_HYPERCALL_FPSWA_PATCH_INDEX)
+#define FW_HYPERCALL_FPSWA 0x500UL
+
/* Hypercalls index bellow _FIRST_ARCH are reserved by Xen, while those above
are for the architecture.
Note: this limit was defined by Xen/ia64 (and not by Xen).²
*/
#define FW_HYPERCALL_FIRST_ARCH 0x300UL
-#define FW_HYPERCALL_IPI 0x400UL
-
/* Xen/ia64 user hypercalls. Only used for debugging. */
#define FW_HYPERCALL_FIRST_USER 0xff00UL
#include <asm/vmx_platform.h>
#include <xen/list.h>
#include <xen/cpumask.h>
+#include <asm/fpswa.h>
extern void domain_relinquish_resources(struct domain *);
unsigned long initrd_start;
unsigned long initrd_len;
char *cmdline;
+ /* There are these for EFI_SET_VIRTUAL_ADDRESS_MAP emulation. */
int efi_virt_mode; /* phys : 0 , virt : 1 */
+ /* Metaphysical address to efi_runtime_services_t in domain firmware memory is set. */
void *efi_runtime;
+ /* Metaphysical address to fpswa_interface_t in domain firmware memory is set. */
+ void *fpswa_inf;
};
#define xen_vastart arch.xen_vastart
#define xen_vaend arch.xen_vaend
//for phycial emulation
unsigned long old_rsc;
int mode_flags;
+ fpswa_ret_t fpswa_ret; /* save return values of FPSWA emulation */
struct arch_vmx_struct arch_vmx; /* Virtual Machine Extensions */
};